package com.yifang.yibingproject.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifang.yibingproject.dto.*;
import com.yifang.yibingproject.entity.SysAuthEntity;
import com.yifang.yibingproject.entity.SysRoleEntity;
import com.yifang.yibingproject.entity.SysUserEntity;
import com.yifang.yibingproject.entity.SysUserRoleEntity;
import com.yifang.yibingproject.exception.ServiceException;
import com.yifang.yibingproject.mapper.SysUserMapper;
import com.yifang.yibingproject.query.ForbiddenPageQuery;
import com.yifang.yibingproject.query.StaffPageQuery;
import com.yifang.yibingproject.service.SysAuthService;
import com.yifang.yibingproject.service.SysRoleService;
import com.yifang.yibingproject.service.SysUserRoleService;
import com.yifang.yibingproject.service.SysUserService;
import com.yifang.yibingproject.utils.EntityUtils;
import com.yifang.yibingproject.utils.StringUtilOwn;
import com.yifang.yibingproject.utils.SystemContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements SysUserService, UserDetailsService {


    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Autowired
    private SysAuthService sysAuthService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 查询用户
        LambdaQueryWrapper<SysUserEntity> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(SysUserEntity::getUsername,username);
        lambdaQueryWrapper.last("limit 1");
        SysUserEntity user = getOne(lambdaQueryWrapper);
        if (user == null) {
            throw new UsernameNotFoundException("用户名或密码错误！");
        }

        // 查询用户角色
        List<SysRoleEntity> roleList = sysUserRoleService.listRolesByUserId(user.getId());
        if (!roleList.isEmpty()) {
            // 授权用户角色
            for (SysRoleEntity role : roleList) {
                SysAuthEntity auth = new SysAuthEntity();
                auth.setPerms("ROLE_" + role.getName());
                // 添加到用户权限中
                user.getAuthEntitySet().add(auth);

                // 查询角色权限
                List<SysAuthEntity> authList = sysAuthService.listAuthsByRoleId(role.getId());
                // 添加角色下所有权限到用户权限集合中
                user.getAuthEntitySet().addAll(authList);
            }
        }
        return user;
    }




    /**
     * 获取用户信息
     * @return
     */
    @Override
    public CurrentUserInfoDTO getCurrentUserInfo() {
        SysUserEntity entity = getById(SystemContext.getCurrentUserId());
        if (entity != null) {
            CurrentUserInfoDTO dto = new CurrentUserInfoDTO();
            BeanUtils.copyProperties(entity, dto);
            return dto;
        }
        return null;
    }


    /**
     * 清楚用户类型
     * @param id
     * @return
     */
    @Override
    public Boolean clearUserType(String id) {
        //删除增值服务关联数据
        return update(new UpdateWrapper<SysUserEntity>()
                .eq("id", id)
                .set("user_type_id", null)//用户类型id清空
                .set("adjust_price", 0)//调价清零
                .set("member_open_state", 0)//会员开通状态改为未开通
                .set("start_time", null)//清除用户类型开通时间
                .set("end_time",null)
                .set("buy_label", null)//可购买标签清空
                .set("update_time", LocalDateTime.now())
                .set("update_by",SystemContext.getCurrentUserId()));
    }

    /**
     * 保存用户权限操作
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public boolean saveActionRight(ActionRightEditDTO dto) {
        SysUserEntity user = checkUserEntity(dto.getUserId());

        //更新用户信息
        UpdateWrapper<SysUserEntity> wrapper = Wrappers.update();
        //标签处理 服务商标签不可降级
        boolean flag = false;
        //现在是否含有采购商标签
        wrapper.set("customer_service_label_id", null);
        wrapper.eq("id", user.getId());
        wrapper.set("update_time", LocalDateTime.now());
        wrapper.set("update_by", SystemContext.getCurrentUserId());
        wrapper.set("user_type_id", dto.getUserTypeId());
        wrapper.set("start_time", dto.getStartTime());
        wrapper.set("end_time", dto.getEndTime());

        wrapper.set("buy_label", dto.getBuyLabel());
        wrapper.set("adjust_price", dto.getAdjustPrice());

        return update(wrapper);
    }

    /**
     * 获取员工列表
     * @param query
     * @return
     */
    @Override
    public Page<StaffDTO> staffList(StaffPageQuery query) {
        Page<SysUserEntity> page = new Page<>(query.getPageNo(), query.getPageSize());
        QueryWrapper<SysUserEntity> wrapper = Wrappers.query();
        wrapper.select("id", "username", "nickname", "real_name", "mobile", "avatar", "status", "gender", "last_login_time", "last_login_ip");
        if (StringUtilOwn.notEmpty(query.getUsername())) {
            wrapper.like("username", query.getUsername());
        }
        if (StringUtilOwn.notEmpty(query.getNickname())) {
            wrapper.like("nickname", query.getNickname());
        }
        if (StringUtilOwn.notEmpty(query.getRealName())) {
            wrapper.like("real_name", query.getRealName());
        }
        if (StringUtilOwn.notEmpty(query.getMobile())) {
            wrapper.like("mobile", query.getMobile());
        }
        if (query.getGender() != null) {
            wrapper.eq("gender", query.getGender());
        }
        if (query.getStatus() != null) {
            wrapper.eq("status", query.getStatus());
        }
        wrapper.orderByDesc("create_time");
        page = page(page, wrapper);
        Page<StaffDTO> dtoPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        if (!CollectionUtils.isEmpty(page.getRecords())) {
            List<StaffDTO> dtoList = new ArrayList<>();
            for (SysUserEntity user : page.getRecords()) {
                StaffDTO dto = new StaffDTO();
                BeanUtils.copyProperties(user, dto);
                dtoList.add(dto);
                //获取员工的角色
                dto.setRoleList(sysRoleService.getRoleNameByUserId(user.getId()));
            }
            dtoPage.setRecords(dtoList);
        }
        return dtoPage;
    }



    /**
     * 删除员工
     * @param id
     * @return
     */
    @Override
    public String delStaff(String id) {
        UpdateWrapper<SysUserEntity> wrapper = Wrappers.update();
        wrapper.eq("id", id);
        wrapper.set("is_deleted", true);
        wrapper.set("update_time", LocalDateTime.now());
        wrapper.set("update_by", SystemContext.getCurrentUserId());
        update(wrapper);
        return id;
    }


    @Override
    public UserDetailDTO getUserDetail(String id) {
        SysUserEntity entity = checkUserEntity(id);
        UserDetailDTO dto = new UserDetailDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

    /**
     * 禁用账户
     * @param id
     * @param reason
     * @return
     */
    @Override
    public boolean forbidden(String id, String reason) {
        UpdateWrapper<SysUserEntity> wrapper = Wrappers.update();
        wrapper.eq("id", id);
        wrapper.set("status", 2);
        wrapper.set("forbidden_reason", reason);
        wrapper.set("forbidden_time", LocalDateTime.now());
        wrapper.set("update_by", SystemContext.getCurrentUserId());
        wrapper.set("update_time", LocalDateTime.now());
        return update(wrapper);
    }

    /**
     * 解禁账户
     * @param id
     * @return
     */
    @Override
    public boolean liftBan(String id) {
        UpdateWrapper<SysUserEntity> wrapper = Wrappers.update();
        wrapper.eq("id", id);
        wrapper.set("status", 1);
        wrapper.set("forbidden_reason", null);
        wrapper.set("forbidden_time", null);
        wrapper.set("update_by", SystemContext.getCurrentUserId());
        wrapper.set("update_time", LocalDateTime.now());
        return update(wrapper);
    }

    /**
     * 禁用账户列表
     * @param query
     * @return
     */
    @Override
    public Page<ForbiddenDTO> forbiddenList(ForbiddenPageQuery query) {
        QueryWrapper<SysUserEntity> wrapper = Wrappers.query();
        wrapper.eq("status", 2);
        Optional.ofNullable(query.getNickname()).filter(StringUtilOwn::notEmpty).ifPresent(n -> wrapper.like("nickname", n));
        Optional.ofNullable(query.getMobile()).filter(StringUtilOwn::notEmpty).ifPresent(m -> wrapper.eq("mobile", m));
        Optional.ofNullable(query.getType()).filter(StringUtilOwn::notEmpty).ifPresent(t -> wrapper.eq("identity", t));
        Optional.ofNullable(query.getStartCostTime()).ifPresent(t -> wrapper.ge("last_cost_time", t));
        Optional.ofNullable(query.getEndCostTime()).ifPresent(t -> wrapper.le("last_cost_time", t));
        Optional.ofNullable(query.getStartCreateTime()).ifPresent(t -> wrapper.ge("create_time", t));
        Optional.ofNullable(query.getEndCreateTime()).ifPresent(t -> wrapper.le("create_time", t));
        IPage<SysUserEntity> page = new Page<>(query.getPageNo(), query.getPageSize());
        page = page(page, wrapper);
        Page<ForbiddenDTO> forPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());

        List<ForbiddenDTO> dtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(page.getRecords())) {
            Set<Long> refIds = page.getRecords().stream().map(SysUserEntity::getId).collect(Collectors.toSet());
            for (SysUserEntity user : page.getRecords()) {
                ForbiddenDTO dto = new ForbiddenDTO();
                BeanUtils.copyProperties(user, dto);
                dtoList.add(dto);
            }
        }
        forPage.setRecords(dtoList);
        return forPage;
    }







    /**
     * 编辑员工信息跳转页面
     * @param id
     * @return
     */
    @Override
    public StaffEditDTO updateStaffpage(Long id) {
        SysUserEntity sysUserEntity = getById(id);
        if (sysUserEntity == null) {
            return null;
        }
        StaffEditDTO staffEditDTO = new StaffEditDTO();
        staffEditDTO.setId(id);
        staffEditDTO.setUsername(sysUserEntity.getUsername());
        staffEditDTO.setAvatar(sysUserEntity.getAvatar());
        staffEditDTO.setGender(sysUserEntity.getGender());
        staffEditDTO.setMobile(sysUserEntity.getMobile());
        staffEditDTO.setNickname(sysUserEntity.getNickname());
        staffEditDTO.setPassword(sysUserEntity.getPassword());
        staffEditDTO.setRealName(sysUserEntity.getRealName());

        List<SysUserRoleEntity> roleEntityList = sysUserRoleService.selectListByUserId(Long.valueOf(id));
        List<Long> roleIdList = roleEntityList.stream().map(SysUserRoleEntity::getRoleId).collect(Collectors.toList());
        staffEditDTO.setRoleIdList(roleIdList);
        return staffEditDTO;
    }

    /**
     * 新增员工
     * @param dto
     * @return
     */
    @Transactional
    @Override
    public String addStaff(StaffEditDTO dto) {
        checkUsernameRepeat(dto.getUsername());
        SysUserEntity entity = EntityUtils.init(new SysUserEntity());
        BeanUtils.copyProperties(dto, entity);
        entity.setStatus(1);
        // 设置加密密码
        entity.setPassword(passwordEncoder.encode(entity.getPassword()));
        save(entity);
        Long userId = entity.getId();

        //保存角色
        if (dto.getRoleIdList() != null && !dto.getRoleIdList().isEmpty()) {
            for (Long roleId : dto.getRoleIdList()) {
                SysUserRoleEntity userRole = EntityUtils.init(new SysUserRoleEntity());
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                sysUserRoleService.save(userRole);
            }
        }

        return "SUCCESS";
    }

    /**
     * 编辑员工信息
     * @param dto
     * @return
     */
    @Override
    @Transactional
    public String updateStaff(StaffEditDTO dto) {
        Long userId = dto.getId();
        SysUserEntity sysUserEntity = getById(userId);
        if (sysUserEntity == null) {
            return null;
        }
        //去掉空格
        String username = StringUtilOwn.trim(dto.getUsername());
        if (!username.equals(sysUserEntity.getUsername())) {
            //判断用户名是否重复
            checkUsernameRepeat(username);
        }

        String passWord;
        //判断密码是否为空 若为空，不修改密码
        if (StringUtilOwn.isEmpty(dto.getPassword())) {
            passWord = sysUserEntity.getPassword();
        } else {
            passWord = passwordEncoder.encode(dto.getPassword());
        }
        sysUserEntity.setUsername(username);
        sysUserEntity.setPassword(passWord);
        sysUserEntity.setNickname(dto.getNickname());
        sysUserEntity.setRealName(dto.getRealName());
        sysUserEntity.setMobile(dto.getMobile());
        sysUserEntity.setAvatar(dto.getAvatar());
        sysUserEntity.setGender(dto.getGender());
        //更新用户信息
        updateById(sysUserEntity);
        //删除角色
        Set<Long> roleIds = sysUserRoleService.listRoleIdsByUserId(userId);
        //保存角色
        if (dto.getRoleIdList() != null && !dto.getRoleIdList().isEmpty()) {
            for (Long roleId : dto.getRoleIdList()) {
                if(roleIds.contains(roleId)){
                    continue;
                }
                SysUserRoleEntity userRole = EntityUtils.init(new SysUserRoleEntity());
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                sysUserRoleService.save(userRole);
            }
        }

        //取消角色
        Optional.ofNullable(roleIds.stream().filter(item->!dto.getRoleIdList().contains(item)).collect(Collectors.toSet())).ifPresent(deleted->{
            if(deleted.isEmpty()){
                return;
            }
            LambdaUpdateWrapper<SysUserRoleEntity> update = new LambdaUpdateWrapper();
            update.in(SysUserRoleEntity::getRoleId,deleted);
            update.eq(SysUserRoleEntity::getUserId,userId);
            sysUserRoleService.remove(update);
        });

        return "SUCCESS";
    }


    /**
     * 根据用户ID集合获取用户列表
     * @param ids
     * @return
     */
    @Override
    public List<SysUserEntity> safetyGetListByIds(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return new ArrayList<>();
        }
        List<SysUserEntity> list = listByIds(ids);
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }
        return list;
    }

    /**
     * 检查用户名是否重复
     *
     * @param username
     */
    private void checkUsernameRepeat(String username) {
        QueryWrapper<SysUserEntity> wrapper = Wrappers.query();
        wrapper.eq("username", username);
        wrapper.last("limit 1");
        SysUserEntity one = getOne(wrapper);
        if (one != null) {
            throw new RuntimeException("用户名已存在");
        }
    }

    private SysUserEntity checkUserEntity(String id) {
        SysUserEntity entity = getById(id);
        if (entity == null) {
            throw new RuntimeException("用户不存在");
        }
        return entity;
    }
}
